#ifndef _ERP_GIS_CORE_AO_ASYN_PROTOCOL_H_
#define _ERP_GIS_CORE_AO_ASYN_PROTOCOL_H_

#include <set>
#include <vector>
#include "giscoreao_liber.h"
#include "gismapgatewayao/include/gismapgatewayao_stub4app_allinone.h"
#include "c2cplatform/library/the3/itil/c2c_attr.h"
#include "c2cent/library/log/CWTimeElf3.h"

#include "erp/gis/po/coordinatesquerypo_gis.h"
#include "erp/gis/po/coordinatespo_gis.h"


using namespace erp::gis::po;

namespace erp
{
namespace gis
{
namespace ao
{

#define PROTOCOLCLOSEITIL		    647676

enum Sys_Err_Code
{
	ERR_SYS_SEND_REQUEST_FAILED		=0xFFF1,
	ERR_SYS_SCHEDULE_FAILED			=0xFFF2,
	ERR_SYS_UNKNOWN_RESPONSE		=0xFFF3,
	ERR_SYS_SERIALIZE_FAILED		=0xFFF4,
};

// 异常请求参数类, 可扩展, 有新的异步协议产生，则需扩展类成员。
class CAsynSendParamBo
{
	public:
		void SetCoordinateQueryPo(CCoordinatesQueryPo& oCoordinateQueryPo)
		{
			m_oCoordinateQueryPo = oCoordinateQueryPo;
		}

		void SetRequestApiType(const std::set<uint32_t>& setMapApiType)
		{
			m_setMapApiType = setMapApiType;
		}

		void GetRequestApiType(std::set<uint32_t>& setMapApiType) const
		{
			setMapApiType = m_setMapApiType;
		}
		
		void GetCoordinateQueryPo(CCoordinatesQueryPo& oCoordinateQueyrPo) const
		{
			oCoordinateQueyrPo = m_oCoordinateQueryPo;
		}

	private:

		/*
		 * 针对请求 CGisMapGatewayAsynProtocol协议的请求参数
		 * m_setMapApiType:      请求的网关地图类型集合
		 * m_oCoordinateQueryPo: 请求获取网关经纬度参数
		 */
		std::set<uint32_t>  m_setMapApiType;
		CCoordinatesQueryPo m_oCoordinateQueryPo;
};

// 异步请求响应结果类, 有新的异步协议结果产生，只需扩展类成员
class CAsynRecvResultBo
{
	public:
		void SetCoordinateResult(const std::map<uint32_t, std::vector<CCoordinatesPo> >& mapApiMap2Coordinates)
		{
			m_mapApiMap2Coordinates = mapApiMap2Coordinates;
		}

		void SetApiMapResponseErr(const std::map<uint32_t, uint32_t>& mapApiMap2RspErr)
		{
			m_mapApiMap2RspErr = mapApiMap2RspErr;
		}

		void AddCoordiantes(uint32_t dwApiMap, const std::vector<CCoordinatesPo>& vecCoordiantes)
		{
			m_mapApiMap2Coordinates[dwApiMap] = vecCoordiantes;
		}

		void AddApiMapResponseErr(uint32_t dwApiMap, uint32_t dwErrCode)
		{
			m_mapApiMap2RspErr[dwApiMap] = dwErrCode;
		}

		void GetCoordinateResult(std::map<uint32_t, std::vector<CCoordinatesPo> >& mapApiMap2Coordinates) const
		{
			mapApiMap2Coordinates =  m_mapApiMap2Coordinates;
		}
		
		
	private:
		/*
		 * 针对请求 CGisMapGatewayAsynProtocol协议的结果集
		 * m_mapApiMap2RspErr：                 网关地图类型的响应错误码
		 * m_mapApiMap2Coordinates: 网关地图类型对应的经纬度集合
		 */
		std::map<uint32_t, uint32_t> m_mapApiMap2RspErr;
		std::map<uint32_t, std::vector<CCoordinatesPo> > m_mapApiMap2Coordinates;
};


class CAsynProtocol
{
	public:
		CAsynProtocol(
			const std::string& strParentName,
			const uint32_t dwAlarmThreshold,
			const uint32_t dwCloseThreshold,
			const uint32_t dwCloseDuration,
			const uint32_t dwExtType,
			const bool bOpen,
			const bool bDump):
			m_strParentName(strParentName),
			m_dwAlarmThreshold(dwAlarmThreshold),
			m_dwCloseThreshold(dwCloseThreshold),
			m_dwCloseDuration(dwCloseDuration),
			m_dwExtType(dwExtType),
			m_bOpen(bOpen),
			m_bDump(bDump){};
		virtual ~CAsynProtocol(){};
		virtual uint32_t Send(
				const CCntlInfo& rCntlInfo,
				const std::string& strMachineKey,
				const std::string& strSource,
				uint32_t dwSceneId,
				const CAsynSendParamBo& oAsynSendParamBo,
				const std::string& strInReserve,
				erp::gis::ao::CLiber& oLiber)=0;
		virtual uint32_t Receive(
				const CAsynSendParamBo& oAsynSendParamBo,
				const uint32_t dwChannel,
				CCmdObj& oCmd,
				CAsynRecvResultBo& oAsynRecvResultBo,
				std::string& strErrMsg,
				std::string& strOutReserve,
				erp::gis::ao::CLiber& oLiber,
				c2cent::library::wtimeelf::CWTimeElfItil &oWTimeElf)=0;
		virtual uint32_t IsOpen(
				const erp::gis::ao::CLiber& oLiber)=0;
		virtual bool CheckCustormRetCode(int32_t iRetCode)=0;
		virtual int32_t Check(const int32_t iRetCode,const uint32_t dwReportItil = PROTOCOLCLOSEITIL)
		{
			if(iRetCode >= ERR_SYS_SEND_REQUEST_FAILED || iRetCode == (int32_t)m_dwReqCmd || iRetCode == (int32_t)m_dwRspCmd || iRetCode<0 ||
				!CheckCustormRetCode(iRetCode))
			{
				uint32_t dwNow=time(0);
				if((m_dwCloseTime+m_dwCloseDuration)>dwNow)
				{
					return iRetCode;
				}
				if(m_dwAlarmThreshold!=0&&m_strProtocolName!=""&&(m_dwSysErrNum+1)==m_dwAlarmThreshold)
				{
					//告警
					char szMsg[256];
					snprintf(szMsg,sizeof(szMsg),"%s%s协议连续错误数=%u",m_strParentName.c_str(),m_strProtocolName.c_str(),m_dwAlarmThreshold);
					adv_attr_set2(dwReportItil,sizeof(szMsg),szMsg);
				}
				if(m_dwCloseThreshold!=0&&m_dwCloseDuration!=0&&m_strProtocolName!=""&&(m_dwSysErrNum+1)>=m_dwCloseThreshold)
				{
					m_dwSysErrNum=0;
					m_dwCloseTime=dwNow;
					//告警
					char szMsg[256];
					snprintf(szMsg,sizeof(szMsg),"%s%s协议连续错误数>=%u,该协议被自动屏蔽%u(s)",m_strParentName.c_str(),m_strProtocolName.c_str(),m_dwCloseThreshold,m_dwCloseDuration);
					adv_attr_set2(dwReportItil,sizeof(szMsg),szMsg);
				}
				m_dwSysErrNum++;
			}
			else
			{
				m_dwSysErrNum=0;
			}
			return iRetCode;
		}
		const std::string& GetProtocolName() const
		{
			return m_strProtocolName;
		}
		uint64_t GetKey() const
		{
			return m_ddwKey;
		}
		uint32_t GetReqCmd() const
		{
			return m_dwReqCmd;
		}
		uint32_t GetRspCmd() const
		{
			return m_dwRspCmd;
		}

	protected:
		const std::string& m_strParentName;
		std::string m_strProtocolName;
		uint64_t m_ddwKey; /*no used*/
		uint32_t m_dwReqCmd;
		uint32_t m_dwRspCmd;
		uint32_t m_dwSysErrNum;
		uint32_t m_dwAlarmThreshold;
		uint32_t m_dwCloseThreshold;
		uint32_t m_dwCloseDuration;
		uint32_t m_dwCloseTime;

		// 扩展类型， 针对CGisMapGatewayAsynProtocol， 该字段作为网关地图类型
		uint32_t m_dwExtType;

		bool m_bOpen;
		bool m_bDump;
};


class CGisMapGatewayAsynProtocol :public CAsynProtocol
{
	public:
		CGisMapGatewayAsynProtocol(
				const std::string& strParentName,
				const uint32_t dwDefTime,
				const uint32_t dwAlarmThreshold,
				const uint32_t dwCloseThreshold,
				const uint32_t dwCloseDuration,
				const uint32_t dwApiType,
				const bool bOpen,
				const bool bDump);
		~CGisMapGatewayAsynProtocol();
		uint32_t Send(
				const CCntlInfo& rCntlInfo,
				const std::string& strMachineKey,
				const std::string& strSource,
				uint32_t dwSceneId,
				const CAsynSendParamBo& oAsynSendParamBo,
				const std::string& strInReserve,
				erp::gis::ao::CLiber& oLiber);
		uint32_t Receive(
				const CAsynSendParamBo& oAsynSendParamBo,
				const uint32_t dwChannel,
				CCmdObj& oCmd,
				CAsynRecvResultBo& oAsynRecvResultBo,
				std::string& strErrMsg,
				std::string& strOutReserve,
				erp::gis::ao::CLiber& oLiber,
				c2cent::library::wtimeelf::CWTimeElfItil &oWTimeElf);
		uint32_t IsOpen(
				const erp::gis::ao::CLiber& oLiber);
		bool CheckCustormRetCode(int32_t iRetCode);
	private:
		uint32_t SendGetCoordinate(
				const CCntlInfo& rCntlInfo,
				const std::string& strMachineKey,
				const std::string& strSource,
				uint32_t dwSceneId,
				const CAsynSendParamBo& oAsynSendParamBo,
				const std::string& strInReserve);
		uint32_t ReceiveCoordinate(
				CCmdObj& oCmd,
				CAsynRecvResultBo& oAsynRecvResultBo,
				std::string& strErrMsg,
				std::string& strOutReserve);

	private:
		static std::string 		  m_strLogModule; // 日志模块
		
		erp::gis::ao::CGisMapGatewayAoStub4App m_oStub;
		std::vector<c2cent::library::wtimeelf::CItilGroup> m_vecItilGroup;
};



}
}
}

#endif
